package startup

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"

	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/errcode"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/common/utils"
	"git.mycaigou.com/gfyx/micro-gfyx-user-service/infrastructure/di"
	pb "git.mycaigou.com/gfyx/micro-gfyx-user-service/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service"
	tenantPb "git.mycaigou.com/gfyx/micro-gfyx-user-service/proto/micro_gfyx_user_service_proto/micro-gfyx-user-service/tenant"
	"git.mycaigou.com/ycg/stark-extend/go2skyplugins/go2skygrpc"
	"git.myscrm.cn/golang/common/ykerrcode"
	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
	grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
	grpc_ctxtags "github.com/grpc-ecosystem/go-grpc-middleware/tags"
	"github.com/grpc-ecosystem/grpc-gateway/runtime"
	"google.golang.org/grpc"
)

// RegisterGRPCServer 此处注册pb的Server
func RegisterGRPCServer(grpcServer *grpc.Server) error {
	s := grpcServer
	var errs []error
	inject := di.NewInject()
	err := inject.Invoke(func(userInfoServer pb.UserInfoServiceServer) {
		pb.RegisterUserInfoServiceServer(s, userInfoServer)
	})

	err = inject.Invoke(func(userLoginServer pb.UserLoginServiceServer) {
		pb.RegisterUserLoginServiceServer(s, userLoginServer)
	})

	err = inject.Invoke(func(organizationServiceServer pb.OrganizationServiceServer) {
		pb.RegisterOrganizationServiceServer(s, organizationServiceServer)
	})

	err = inject.Invoke(func(FileServiceServer pb.FileServiceServer) {
		pb.RegisterFileServiceServer(s, FileServiceServer)
	})

	err = inject.Invoke(func(reportServiceServer pb.ReportServiceServer) {
		pb.RegisterReportServiceServer(s, reportServiceServer)
	})
	//需要划分到租户域，待重构
	err = inject.Invoke(func(tenantServiceServer tenantPb.TenantServiceServer) {
		tenantPb.RegisterTenantServiceServer(s, tenantServiceServer)
	})

	err = inject.Invoke(func(verifyCodeServiceServer pb.VerifyCodeServiceServer) {
		pb.RegisterVerifyCodeServiceServer(s, verifyCodeServiceServer)
	})

	err = inject.Invoke(func(server pb.MiniProgramServiceServer) {
		pb.RegisterMiniProgramServiceServer(s, server)
	})

	err = inject.Invoke(func(server pb.CustomerGroupServiceServer) {
		pb.RegisterCustomerGroupServiceServer(s, server)
	})

	_ = inject.Invoke(func(server pb.StrategicMonitorServiceServer) {
		pb.RegisterStrategicMonitorServiceServer(s, server)
	})

	_ = inject.Invoke(func(server pb.SiteAnnouncementServiceServer) {
		pb.RegisterSiteAnnouncementServiceServer(s, server)
	})

	//租户域，按领域划分
	err = inject.Invoke(func(
		tenantServiceServer tenantPb.CreateTenantServiceServer,
	) {
		tenantPb.RegisterCreateTenantServiceServer(s, tenantServiceServer)
	})
	errs = append(errs, err)

	if err != nil {
		fmt.Printf("RegisterGRPCServer err: %+v\n", err)
		return err
	}

	if len(errs) > 0 {
		fmt.Printf("RegisterGRPCServer err: %+v\n", errs[0])
		return err
	}

	fmt.Printf("RegisterGRPCServer successful\n")
	return nil
}

// RegisterGateway 此处注册pb的Gateway
func RegisterGateway(ctx context.Context, gateway *runtime.ServeMux, endPoint string, dopts []grpc.DialOption) error {
	var err error
	if err = pb.RegisterUserInfoServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = pb.RegisterUserLoginServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = pb.RegisterOrganizationServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = pb.RegisterFileServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = pb.RegisterVerifyCodeServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	if err = tenantPb.RegisterCreateTenantServiceHandlerFromEndpoint(ctx, gateway, endPoint, dopts); err != nil {
		return err
	}
	return nil
}

func RegisterMiddleware() []grpc.UnaryServerInterceptor {
	myAuthFunction := func(ctx context.Context) (context.Context, error) {
		bearer, err := grpc_auth.AuthFromMD(ctx, "bearer")
		splits := strings.SplitN(bearer, ".", 2)
		if len(splits) < 2 {
			return nil, ykerrcode.TogRPCError(
				errcode.COMMON_TOKEN_ERROR, fmt.Sprintf("bearer is null, bearer: %s, err: %+v", bearer, err))
		}

		//token := splits[0]
		data := splits[1]

		authInfo := utils.AuthInfo{}
		err = json.Unmarshal([]byte(data), &authInfo)
		if err != nil {
			return nil, ykerrcode.TogRPCError(errcode.COMMON_TOKEN_ERROR, err.Error())
		}
		//
		//acUsercase := di.NewAccessTokenDi()

		// WARNING: in production define your own type to avoid context collisions
		newCtx := context.WithValue(ctx, "app_id", authInfo)
		return newCtx, nil
	}

	unaryInterceptor := grpc_middleware.ChainUnaryServer(
		grpc_ctxtags.UnaryServerInterceptor(),
		grpc_auth.UnaryServerInterceptor(myAuthFunction),
		go2skygrpc.NewUnaryServerInterceptor(),
	)

	return []grpc.UnaryServerInterceptor{unaryInterceptor}
}
